package com.iamk.util;

import java.util.ArrayList;

import weka.classifiers.Classifier;
import weka.classifiers.Evaluation;
import weka.core.Instances;
import weka.filters.unsupervised.instance.RemoveFolds;

public class ClassifierUtil {
	public boolean isUseCV;
	public int fold;
	public double mExpectation;
	public double mVariance;
	public Classifier cls;
	ArrayList<Double> arrError;
	int nIter = 10;
	int nFolds = 10;
	Evaluation eval;

	public ClassifierUtil(boolean isUseCV, int fold, Classifier cls) {
		this.isUseCV = isUseCV;
		this.fold = fold;
		this.cls = cls;
		arrError = new ArrayList<Double>();
	}

	public double[][] getDistributions(Instances structure, int folds) {
		double[][] pDistribution = null;
		int instanceIndex = 0;
		double totalError = 0;
		double totalVar = 0;
		try {
			structure.setClassIndex(structure.numAttributes() - 1);
			// perform cross-validation
			for (int i = 0; i < nIter; i++) {
				for (int n = 0; n < folds; n++) {
					RemoveFolds rf = new RemoveFolds();
					rf.setSeed(0);
					rf.setInvertSelection(true);
					rf.setFold(n+1);
					rf.setNumFolds(10);
					rf.setInputFormat(structure);
					Instances train = RemoveFolds.useFilter(structure, rf);
					train.setClassIndex(train.numAttributes() - 1);

					RemoveFolds rfTest = new RemoveFolds();
					rfTest.setSeed(0);
					rfTest.setInvertSelection(false);
					rfTest.setFold(n+1);
					rfTest.setNumFolds(10);
					rfTest.setInputFormat(structure);
					Instances test = RemoveFolds.useFilter(structure, rfTest);
					test.setClassIndex(test.numAttributes() - 1);		
					
					// build and evaluate classifier
					Evaluation eval = new Evaluation(train);
//					Classifier clsCopy = Classifier.makeCopy(cls);
//					clsCopy.buildClassifier(train);
//					eval.evaluateModel(clsCopy, test);
					arrError.add(eval.errorRate());
				}
			}
			// System.out.println("Total: " + totalError + "/folds: " + folds);
			for (int i = 0; i < arrError.size(); i++) {
				totalError += arrError.get(i);
			}
			this.mExpectation = (double) (totalError / (nFolds * nIter));
			for (int i = 0; i < arrError.size(); i++) {
				totalVar = Math.pow((arrError.get(i) - mExpectation), 2);
			}
			this.mVariance = (double) (totalVar / (nFolds * nIter));

		} catch (Exception e) {
			e.printStackTrace();
		}
		return pDistribution;
	}
}
